/*
 * @Author: LVGRAPE
 * @Date: 2023-11-09 10:56:37
 * @LastEditTime: 2023-11-15 15:29:13
 * @LastEditors: LVGRAPE
 * @Description:
 * @FilePath: \zino_fc_v0\zino\power\pwr_key.c
 * 要啥没啥，爱咋咋的
 */
#include "zino.h"
#include "zino_pin.h"
#include "os_timer.h"
#include <stdbool.h>
#define DBG_TAG "pwr_key"
#define DBG_LVL DBG_ERROR
#include <rtdbg.h>
#include <stdlib.h>

#define KEY_DOWN_MASK  0X80/**按下标记*/
#define KEY_LONG_PRESS_MASK  0X40/**长按标记 */
#define KEY_TIMEOUT_MASK  0X10/**超时标志，此时返回按键值*/
#define KEY_TIEMES_MASK  0X0F/**按了多少次 */
#define KEY_VALUE(x) (0x0001<<(x))


struct pwrKeyActList {
    hb_key_action_callback_t cb;
    struct pwrKeyActList* next;
};

static zino_io_t pwr_key_io = { GPIOA, GPIO_Pins_0 };
static os_timer_t hb_timer;
static struct pwrKeyActList pwrKeyActListHead = { 0 };
static hb_key_longpress_callback_t pwrKeyLongPressCb = NULL;
static void pwrKeyLongPressCbDefault(void)
{
    rt_kprintf("long press detect. Use pwrKey_longPress_action_attach() to add your code.\n");
}
void pwrKey_longPress_action_attach(hb_key_longpress_callback_t cb)
{
    pwrKeyLongPressCb = cb;
}
void pwrKey_action_add(hb_key_action_callback_t cb)
{
    if(!pwrKeyActListHead.cb)
    {
        pwrKeyActListHead.cb = cb;
        // LOG_D("First:0x%08X", &pwrKeyActListHead);
    }
    else
    {
        struct pwrKeyActList* new = (struct pwrKeyActList*)malloc(sizeof(struct pwrKeyActList));
        if (new == NULL)
        {
            LOG_E("malloc pwrKeyAct_list failed");
            return;
        }
        new->cb = cb;
        new->next = NULL;

        struct pwrKeyActList* p;
        p = &pwrKeyActListHead;
        while (p->next) p = p->next;
        p->next = new;
        // LOG_D("p:0x%08X", p);
        // LOG_D("new:0x%08X", new);
    }

}

#define KEY_COUNTS 1
void keyScanPro()
{

    const uint8_t SHORT_PRESS_TIME = 25;
    const uint8_t LONG_PRESS_TIME = 100;
    const uint8_t IS_KEY_DOWN = 0X80;/**按下了 */
    const uint8_t IS_LONG_PRESS = 0X40;/**长按了 */
    const uint8_t IS_TIME_OUT = 0X10;/**退好久没按 */
    static uint8_t pressTimesRecord[KEY_COUNTS] = { 0 };
    static uint8_t pressTime[KEY_COUNTS] = { 0 };
    static uint8_t longPressTime[KEY_COUNTS] = { 0 };
    const uint16_t channel_keyScan_map[KEY_COUNTS] = { 1 };/**A,B,C,D,E,F,G,H,I,J,K,L对就的键值*/

    zino_pin_mode(&pwr_key_io, ZINO_PIN_MODE_INPUT);
    uint16_t keyValue = zino_pin_read(&pwr_key_io);
    for (uint8_t i = 0; i < KEY_COUNTS; i++)
    {
        if (keyValue == channel_keyScan_map[i])
        {
            //按下了
            if (longPressTime[i] < LONG_PRESS_TIME)
            {
                longPressTime[i]++;
                pressTime[i] = SHORT_PRESS_TIME;
                pressTimesRecord[i] |= IS_KEY_DOWN;

            }
            else
            {
                pressTimesRecord[i] |= IS_LONG_PRESS;
                pressTimesRecord[i] |= IS_TIME_OUT;
                pressTimesRecord[i] &= ~IS_KEY_DOWN; //取消标记高位
                LOG_D("long press\n");
                if(pwrKeyLongPressCb) pwrKeyLongPressCb();
                    else pwrKeyLongPressCbDefault();
            }

        }
        else
        {
            //松开了
            longPressTime[i] = 0;
            if (pressTimesRecord[i] & IS_KEY_DOWN)
            {
                //高位标记过，即按下过
                pressTimesRecord[i] &= ~IS_KEY_DOWN; //取消标记高位
                if ((pressTimesRecord[i] & KEY_TIEMES_MASK) < 15)
                {
                    pressTimesRecord[i]++;
                }

            }
            if (pressTime[i] > 0)
            {
                if (pressTime[i] == 1)
                {
                    pressTimesRecord[i] |= IS_TIME_OUT;//BIT4 为检测时间到
                }
                pressTime[i]--;
            }
            if (pressTimesRecord[i] & IS_TIME_OUT)
            {

                if (pressTimesRecord[i] & IS_LONG_PRESS)
                {
                    // rt_kprintf("Long press:%d \n", i);
                    pressTimesRecord[i] &= ~IS_LONG_PRESS;
                    
                    
                }
                else if (pressTimesRecord[i] & KEY_TIEMES_MASK)
                {
                    uint8_t ptc = pressTimesRecord[i] & KEY_TIEMES_MASK;
                    struct pwrKeyActList* p;
                    p=&pwrKeyActListHead;
                    do {
                        // LOG_D("P:0x%08X", p);
                        if (p->cb)
                        {
                            p->cb(ptc);
                        }
                        p = p->next;
                    } while (p);
                }
                // LOG_I("Press:%d - %d\n", i, pressTimesRecord[i] & KEY_TIEMES_MASK);;
                pressTimesRecord[i] = 0;
            }
        }
    }
}



void hb_longpress_action()
{
    // LOG_I("hb_longpress_action... \r\n");
    // LOG_I("power shutting down... \r\n");
    // zino_pwr_ctrl(PWR_CTRL_SHUTDOWN);
}
void hb_cat1(uint8_t times)
{
    if(times == 1)
    rt_kprintf("act1 %d\n", times);
}
void hb_cat2(uint8_t times)
{
    if(times == 2)
    rt_kprintf("act2 %d\n", times);
}
void hb_cat3(uint8_t times)
{
    if(times == 3)
    rt_kprintf("act3 %d\n", times);
}
int home_botton_init()
{
    // hb_timer = rt_timer_create("hb trace", keyScanPro, RT_NULL, 20, RT_TIMER_FLAG_PERIODIC);
    // if (hb_timer == RT_NULL)
    // {
    //     rt_kprintf("error in creat hb timer.\n");
    //     rt_kprintf("home_botton_init failure.\n");
    //     return -RT_ERROR;
    // }
    // rt_pin_mode(PWR_KEY_PIN, PIN_MODE_INPUT);
    // rt_pin_attach_irq(PWR_KEY_PIN, PIN_IRQ_MODE_RISING, hb_trace_isr, RT_NULL);
    // rt_pin_irq_enable(PWR_KEY_PIN, PIN_IRQ_ENABLE);
    LOG_I("home_botton_init... \r\n");
    os_timer_init(&hb_timer, keyScanPro, 0);
    os_timer_start(&hb_timer, 20, 1);

    pwrKey_action_add(hb_cat1);
    pwrKey_action_add(hb_cat2);
    pwrKey_action_add(hb_cat3);
    // rt_timer_start(hb_timer);
    // set_hb_key_long_press_action(hb_longpress_action);
    return 0;
}

ZINO_APP_EXPORT(home_botton_init);